
#include "../Utils/TKuiMicro.h"
#include "TManager.hpp"
#pragma once

namespace Tk{

	template <class T>
	class TkuiHostWnd{
	public:
		TkuiHostWnd(){}

		void SetHWnd(HWND hWnd){m_hWnd =hWnd; }
		HWND GetHWnd()const;

		bool RegisterWindowClass(HINSTANCE hInstance){
			WNDCLASS wc = { 0 };
			wc.style = GetClassStyle();
			wc.cbClsExtra = 0;
			wc.cbWndExtra = 0;
			wc.hIcon = NULL;
			wc.lpfnWndProc = TkuiHostWnd::_WndProc;
			wc.hInstance = hInstance;
			wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
			wc.hbrBackground = NULL;
			wc.lpszMenuName  = NULL;
			wc.lpszClassName = GetWindowClassName();
			ATOM ret = ::RegisterClass(&wc);
			ASSERT(ret!=NULL || ::GetLastError()==ERROR_CLASS_ALREADY_EXISTS);
			return ret != NULL || ::GetLastError() == ERROR_CLASS_ALREADY_EXISTS;
		}

		HWND Create(HINSTANCE hInstance, HWND hwndParent,const RECT rc,HMENU hMenu = NULL){
			if(GetWindowClassName()==NULL ||  !RegisterWindowClass(hInstance))
				return NULL;
			m_hWnd = ::CreateWindowEx(GetExStyle(),GetWindowClassName(),GetWindowName(),GetStyle(),
				rc.left,rc.top,rc.right - rc.left,rc.bottom - rc.top,hwndParent,hMenu,hInstance,this);
			ASSERT(m_hWnd!=NULL);
			return m_hWnd;
		}

		void Show(bool bShow = true,bool bFocus = true){
			ASSERT(::IsWindow(m_hWnd));
			if( !::IsWindow(m_hWnd) ) return;
			::ShowWindow(m_hWnd, bShow ? (bFocus ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE) : SW_HIDE);
		}

	protected:
		virtual LPCTSTR GetWindowClassName() const = 0;
		virtual LPCTSTR GetWindowName() const = 0;
		virtual UINT GetClassStyle() const
		{
			return WS_VISIBLE | WS_OVERLAPPEDWINDOW;
		}
		virtual UINT GetExStyle() const
		{
			return 0;
		}
		virtual UINT GetStyle() const = 0;

		virtual BOOL HandleMessage(UINT uMsg,WPARAM wParam,LPARAM lParam,LRESULT& result)
		{
			return m_manager.HandleMessage(uMsg,wParam,lParam,result);
		}

		virtual void OnFinalMessage(HWND hWnd)
		{

		}

		static LRESULT CALLBACK _WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
		{
			T* pWnd = NULL;
			if(uMsg == WM_NCCREATE)
			{
				LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
				pWnd = static_cast<T*>(lpcs->lpCreateParams);
				pWnd->SetHWnd(hWnd);
				::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(pWnd));
			}
			else
			{
				pWnd = reinterpret_cast<T*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
				if(uMsg == WM_NCDESTROY && pWnd!=NULL)
				{

				}
			}
			if(pWnd !=NULL)
			{
				LRESULT result = 0;
				pWnd->HandleMessage(uMsg,wParam,lParam,result);
				return result;
			}
			else
			{
				return ::DefWindowProc(hWnd,uMsg,wParam,lParam);
			}
		}

	protected:
		HWND m_hWnd;
		TManager m_manager;
	};

	class TkuiHost:public TkuiHostWnd<TkuiHost>
	{
	public:
		TKUI_BEGIN_MSG_MAP(TkuiHost)
			TKUI_MESSAGE_HANDLE(WM_PAINT,OnPaint)
			TKUI_MESSAGE_HANDLE(WM_ERASEBKGND,OnPaint)
			TKUI_CHAIN_MESSAGE_MAP(TkuiHostWnd<TkuiHost>)
			TKUI_END_MSG_MAP()

			BOOL OnEraseBkgnd(UINT uMsg,WPARAM wParam,LPARAM lParam,LRESULT& result)
		{
			result = true;
			return TRUE;
		}

		BOOL OnPaint(UINT uMsg,WPARAM wParam,LPARAM lParam,LRESULT& result)
		{
			PAINTSTRUCT ps ;
			HDC hdc = ::BeginPaint(this->m_hWnd,&ps);
			RECT a = {0,0,100,100};
			::DrawTextA(hdc,"heelo",5,&a,0);
			::EndPaint(this->m_hWnd,&ps);
			return TRUE;
		}

	private:
		TKUI_DECLARE_WND_CLASS(TkuiHost,_T("TkuiHostWnd"),CS_HREDRAW | CS_VREDRAW,0,WS_VISIBLE | WS_CHILD)

			LPCTSTR GetWindowName() const
		{
			return _T("TkuiHost");
		}

	};

}
